package com.lanchetech.user.service.impl;

import com.baidu.fsg.uid.UidGenerator;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.request.GoodSpuListReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.GoodSpuListResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.SkuPriceVO;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.common.util.IpUtil;
import com.lanchetech.dao.AnchorDepositMapper;
import com.lanchetech.dao.ShoppingCartMapper;
import com.lanchetech.dao.SkuMapper;
import com.lanchetech.dao.SpuMapper;
import com.lanchetech.entity.*;
import com.lanchetech.user.config.ReturnPayInfoVO;
import com.lanchetech.user.service.CommonService;
import com.lanchetech.user.service.GlobalGoodSpuService;
import com.lanchetech.user.service.UserService;
import com.sun.org.apache.bcel.internal.generic.NEW;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class GlobalGoodSpuServiceImpl implements GlobalGoodSpuService {

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    UserService userService;

    @Autowired
    SkuMapper skuMapper;

    @Autowired
    ShoppingCartMapper shoppingCartMapper;

    @Resource
    UidGenerator uidGenerator;

    @Autowired
    AnchorDepositMapper anchorDepositMapper;

    @Value("${domain.url}")
    private String domainUrl;

    @Value("${wx.pay.appId}")
    private String miniAppId;

    @Value("${wx.app.appId}")
    private String appAppId;

    @Autowired
    CommonService commonService;

    @Autowired
    RedisTemplate redisTemplate;
    /**
     * 全球好物一级分类商品列表
     * @param goodSpuListReq
     * @return
     */
    @Override
    public ResultData GoodSpuList(GoodSpuListReq goodSpuListReq) {
        goodSpuListReq.setType(OrderKindEnum.ORDINARY.getKind());
        Page page = PageHelper.startPage(goodSpuListReq.getPageNo(), goodSpuListReq.getPageSize());
        List<GoodSpuListResp> goodSpuListVoList = spuMapper.GoodSpuList(goodSpuListReq);
        ResultData<BasePageResp<GoodSpuListResp>> basePageRespResultData = PageHelpUtil.buildPage(goodSpuListVoList, page);
        return basePageRespResultData;
    }

    @Override
    public BaseResp addAgency(User user ) {
        if (user.getLevel().equals(UserLevelEnum.AGENCY.getLevel())){
            return  new BaseResp(ResultCode.AGENCY_YES);
        } else if (!user.getLevel().equals(UserLevelEnum.AGENCY.getLevel())){

            user.setLevel(102);
            user.setCreatedAt(new Date());
            user.setUpdatedAt(new Date());
            spuMapper.addAgency(user);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<SkuPriceVO> getPrice(User user) {
        Sku sku = new Sku();
        SkuPriceVO skuPriceVO = new SkuPriceVO();
        if (user.getAgency().equals(ResultCode.AGENCY_YES)){
            skuPriceVO.setAgency_price(sku.getAgency_price());
            return  new ResultData<>(skuPriceVO);
        }else if (user.getAgency().equals(ResultCode.TALENT_PRICE)){
            skuPriceVO.setIntelligent_price(sku.getIntelligent_price());
            return new ResultData<>(skuPriceVO);
        }else if (user.getAgency().equals(ResultCode.MANUFACTURERRS_PRICE)){
            skuPriceVO.setManufacturers_price(sku.getManufacturers_price());
            return new ResultData<>(skuPriceVO);
        }
        return new ResultData<>();
    }

    @Override
    public ResultData<List<Merchant>> getMerchant(long id) {
        ValueOperations<String, List<Merchant>> operations = redisTemplate.opsForValue();
        String ids = "GetAllMerchantList:" + id;
        List<Merchant> result = operations.get(ids);
        if (result == null) {
            result = spuMapper.getMerchant(id);
            operations.set(ids, result);
        }
        return new ResultData<>(result);
    }

    @Override
    public ResultData<Sku> getOrderSquare(User user, Long id) {
        if (!user.getLevel().equals(UserLevelEnum.AGENCY.getLevel())){
            new ResultCodeException(ResultCode.NO_SHOPSTER);
        }

        Sku sku = spuMapper.selectById(id);
        BigDecimal old = new BigDecimal(String.valueOf(sku.getPrice()));
        BigDecimal discount = new BigDecimal("0.8");
        sku.setAgency_price(old.multiply(discount));

        return new  ResultData<>(sku);
    }

    @Override
    public ResultData<Sku> getSelectionSquare(User user, Long id) {
        if (user.getLevel().equals(UserLevelEnum.AGENCY.getLevel())){
            Sku sku = spuMapper.selectById(id);
            BigDecimal old = new BigDecimal(String.valueOf(sku.getPrice()));
            BigDecimal discount = new BigDecimal("0.8");
            sku.setAgency_price(old.multiply(discount));
            return new  ResultData<>(sku);
        }
        return new ResultData<>(spuMapper.selectById(id));
    }


    private static final int MIN_QUANTITY = 10;
    @Override
    public BaseResp addToShoppingCart(User user, ShoppingCart shoppingCart) {
        if (shoppingCart.getSkuId() == null) {
            Sku sku = skuMapper.findTopOneBySpuId(shoppingCart.getSpuId());
            shoppingCart.setSkuId(sku.getId());
        }

        ShoppingCart result = shoppingCartMapper.findOneByUserIdAndSkuId(user.getId(), shoppingCart.getSkuId());

        if (result == null) {
            // 如果购物车数量小于10件，则不允许小于10件
            Long count = shoppingCartMapper.countByUserId(user.getId());
            if (count <= MIN_QUANTITY) {
                return new BaseResp(ResultCode.OVER_MIN_SHOPPING_CART);
            }

            Spu spu = spuMapper.selectByPrimaryKey(shoppingCart.getSpuId());

            shoppingCart.setUserId(user.getId());
            shoppingCart.setCreatedAt(new Date());
            shoppingCart.setTenantId(spu.getTenantId());
            shoppingCartMapper.insert(shoppingCart);
        } else {
            result.setCount(result.getCount() + shoppingCart.getCount());
            shoppingCartMapper.updateByPrimaryKey(result);
        }

        return new BaseResp();
    }

    @Override
    public ResultData<ReturnPayInfoVO> createAgencyDeposit(User user, Byte type, Long userAddressId, HttpServletRequest httpServletRequest) {
        // TODO 创建代理入驻金要有payWay，支付方式参数

        AgencyDeposit agencyDeposit = AgencyDeposit.builder()
                .anchorUserId(user.getId())
                //todo 测试
                //.amount(ANCHOR_DEPOSIT)
                .amount(new BigDecimal("0.01"))
                .tradeNo(Long.toString(uidGenerator.getUID()))
                .payWay(type)
                .payStatus(AnchorDepositPayStatusEnum.NOT_PAY.getStatus())
                .createdAt(new Date())
                .updatedAt(new Date())
                //todo 默认1
                .userAddressId(3L)
                .build();
        anchorDepositMapper.insertAgency(agencyDeposit);

        // 创建微信支付
        final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                .openid(PayTypeEnum.WECHAT.getType().equals(type) ? user.getOpenid() : null)
                .outTradeNo(agencyDeposit.getTradeNo())
                //订单金额, 单位：分
                .totalFee(agencyDeposit.getAmount().multiply(new BigDecimal(100)).intValue())
                .body("主播保证金")
                .spbillCreateIp(IpUtil.getIpAddr(httpServletRequest))
                .notifyUrl(domainUrl + "/api/anchor/depositWechatPayNotify")
                .build();

        if (PayTypeEnum.WECHAT.getType().equals(agencyDeposit.getPayWay())) {
            wxPayUnifiedOrderRequest.setAppid(miniAppId);
            wxPayUnifiedOrderRequest.setTradeType("JSAPI");
        } else {
            wxPayUnifiedOrderRequest.setAppid(appAppId);
            wxPayUnifiedOrderRequest.setTradeType("APP");
        }

        return new ResultData<>(commonService.getReturnPayInfoVO(wxPayUnifiedOrderRequest));
    }
}
